﻿package com.midia.playerVideo { 
	
	import flash.display.MovieClip;
	import flash.display.SimpleButton;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.geom.Rectangle;
	import flash.ui.ContextMenu;
	import flash.utils.Timer;
	import flash.text.TextField;
	import flash.media.SoundTransform;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.display.StageScaleMode;
	import flash.display.StageAlign;
	import flash.display.StageDisplayState;
	
	import flash.media.Video;
	import flash.net.NetConnection;
	import flash.net.NetStream;
	
	import flash.net.URLRequest;
	import flash.net.URLLoader;
	import flash.xml.XMLDocument;
	
	import flash.events.AsyncErrorEvent;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.events.FullScreenEvent;
		
	import flash.system.Capabilities;
	
	import com.midia.playerVideo.controles.BarraProgresso;
	import com.midia.playerVideo.controles.Barra;
	import com.midia.playerVideo.events.BarraEvent;
	import com.midia.playerVideo.DadosVideo;
	import com.midia.playerVideo.events.PlayerVideoEvent;
	import com.midia.playerVideo.dados.CarregaDadosVideo
	
	import com.effects.Tween;
	import com.events.TweenEvent;
	
	/**
	* Player de Vídeo
	* @author Ricardo Teixeira
	*/
	public class PlayerVideo extends MovieClip {
		private var con:NetConnection;
		private var stream:NetStream;
		private var controlePlay:Boolean;
		private var controleMute:Boolean;
		private var controleFullScreen:Boolean;
		private var tempo:Timer;
		private var _duracao:Number;
		private var volumeAtual:Number;
		private var terminouVideo:Boolean;
		private var _idVideoAtual:uint;
		public var _campo:TextField;
		
		private var volYInicial:Number;
		private var volTween:Tween;
		
		private var dadosVideo:DadosVideo;
		private var _listaDadosVideo:Array;
		private var carregouMetaData:Boolean;
		
		//private var thumb1:Loader;
		//private var thumb2:Loader;
		
		//private var videosRelacionados:Array;
		
		
		//private var dados:URLLoader;
		
		//private var informacoes:LoaderInfo;
		
		public function PlayerVideo ():void {
			//this._campo = this.campo;
			
			/*this.informacoes = this.root.loaderInfo;			
			this.informacoes.addEventListener(Event.COMPLETE, this.onLoadInfo);*/
						
			this.carregouMetaData = false;
			
			this._idVideoAtual = 0;
			this._listaDadosVideo = new Array ();
		
			/*
			var screen:MovieClip = this._screen;
			var contextMenu:ContextMenu = new ContextMenu ();
			contextMenu.hideBuiltInItems ();
			contextMenu.customItems.push ()
			screen.contexMenu
			*/
			
			this.tempo = new Timer (1);
			
			this.volumeAtual = 0.7;
			this.controleMute = true;
			this.controlePlay = true;
			this.controleFullScreen = false;
			this.terminouVideo = false;
			
			this.volYInicial = this.vol.y;			
			this.vol.y = this.vol.y + this.vol.height;
			
			this.configurarControles ();
			this.configurarConexao ();
			this.configurarListeners ();
		}
		
		public function set fullScreen (valor:Boolean):void {
			this.controleFullScreen = valor;
		}
		
		public function get fullScreen ():Boolean {
			return this.controleFullScreen;
		}
		
		public function get status ():TextField {
			return this.progressoTempo.statusTime;
		}
		
		public function set listaDadosVideo (lista:Array):void {
			this._listaDadosVideo = lista;
		}
		
		public function get listaDadosVideo ():Array {
			return this._listaDadosVideo;
		}
		
		public function set idVideoAtual (id:uint):void {
			this._idVideoAtual = id;
		}
		
		public function get idVideoAtual ():uint {
			return this._idVideoAtual;
		}
		
		public function get screen ():Sprite {
			return this._screen;
		}
		
		public function get duracao():Number { 
			return this._duracao; 
		}
		
		/**
		 * Configura o tamanho do video e a visibilidade dos controles
		 * de acordo com o estado FullScreen ou não.
		 * @return void
		 */
		public function organizarControles (isFullScreen:Boolean):void {
			var video:Video = this._screen.videoScreen;
			try {				
				if (isFullScreen) {
					video.height = Capabilities.screenResolutionY; 
					video.scaleX = video.scaleY;
					video.x = (Capabilities.screenResolutionX - video.width) / 2;
					this.estadoControles (false);						
				} else {
					video.width = 480; 
					video.height = 360;
					video.x = 0;
					this.estadoControles (true);
				}
			} catch (e:Error) {
				trace ("Erro: " + e.message);
			}
		}
				
		private function configurarControles ():void {			
			this.btPlay.buttonMode = true;
			this.btMute.buttonMode = true;
			this.btAmpliar.buttonMode = true;
			
			this.btMute.stop ();
			
			//this.vol.visible = false;
			this.vol.perc = this.volumeAtual * 100;
		}
		/*
		public function avancar (p:uint):void {
			if (p > 100) {
				p = 100;
			}
			this.progresso.perc = p;
		}
		
		public function retroceder (p:uint):void {
			if (p < 0) {
				p = 0;
			}
			this.progresso.perc = p;
		}
		*/
		private function configurarConexao ():void {
			this.con = new NetConnection ();
			this.con.connect(null);
			
			this.stream = new NetStream (this.con);
			this.stream.soundTransform = new SoundTransform (this.volumeAtual);
			this.stream.client = this;
						
			this.stream.bufferTime = 10;
			this._screen.videoScreen.attachNetStream (this.stream);
			this._screen.videoScreen.smoothing = true;
		}
		
		private function configurarListeners ():void {
			//this.dados.addEventListener(Event.COMPLETE, this.onLoadDados);
			
			//this.stage.showDefaultContextMenu = false;
			
			this.screen.doubleClickEnabled = true;
			this.screen.addEventListener (MouseEvent.DOUBLE_CLICK, this.onScreenDoubleClick);
			this.screen.addEventListener (MouseEvent.CLICK, this.onScreenClick);
			
			this.tempo.addEventListener(TimerEvent.TIMER, this.onTimer);
			
			this.stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
			
			this.btMute.addEventListener (MouseEvent.ROLL_OVER, this.onMuteOver);	
			this.btMute.addEventListener (MouseEvent.ROLL_OUT, this.onMuteOut);	
			
			this.vol.addEventListener (MouseEvent.ROLL_OVER, this.onMuteOver);
			this.vol.addEventListener (MouseEvent.ROLL_OUT, this.onMuteOut);
			
			this.btMute.addEventListener (MouseEvent.CLICK, this.onMuteClick);		
			this.btAmpliar.addEventListener (MouseEvent.CLICK, this.onAmpliarClick);			
			this.btPlay.addEventListener (MouseEvent.CLICK, this.onPlayClick);
			
			this.vol.addEventListener (BarraEvent.DRAG_MOVE, this.onVolDragMove);	
			
			this.progresso.addEventListener (BarraEvent.DRAG_START, this.onProgDragStart);
			this.progresso.addEventListener (BarraEvent.DRAG_STOP, this.onProgDragStop);
			this.progresso.addEventListener (BarraEvent.DRAG_MOVE, this.onProgDragMove);
			this.progresso.addEventListener (BarraEvent.CLICK_AREA, this.onProgClickArea);
			
			/*this.stage.addEventListener(FullScreenEvent.FULL_SCREEN, this.onFullScreen);
			this.stage.addEventListener(Event.RESIZE, this.onResizeScreen);*/
		}
		
		public function iniciarVideo (pDadosVideo:DadosVideo = null):void {	
			var repetirCarregado:Boolean = false;
			
			/*trace (1);
			if (this.dadosVideo != null) {
				trace (2);
				if (this.dadosVideo.url == this._listaDadosVideo[this._idVideoAtual].url) {
					trace (3);
					repetirCarregado = true;
				} else {
					trace (4);
					this.dadosVideo = this._listaDadosVideo[this._idVideoAtual];
				}
			} else {
				trace (5);
				this.dadosVideo = this._listaDadosVideo[this._idVideoAtual];
			}
			
			if (pDadosVideo == null && this.dadosVideo == null) {
				
				this.dadosVideo = this._listaDadosVideo[this._idVideoAtual];
			} else if (pDadosVideo == null) {
				if (this.dadosVideo.url == this._listaDadosVideo[this._idVideoAtual].url) {
					repetirCarregado = true;
				} else {
					this.dadosVideo = this._listaDadosVideo[this._idVideoAtual];
				}				
			} else {
				if (this.dadosVideo.url == pDadosVideo.url) {
					repetirCarregado = true;
				} else {
					this.dadosVideo = pDadosVideo;
				}				
			}*/
			
			// TODO: rever se o pode usar o seek para nao recarregar
			this.dadosVideo = this._listaDadosVideo[this._idVideoAtual];
			
			var video:DadosVideo = this.dadosVideo;
			var urlVideo:String = video.url;
			
			this.btPlay.gotoAndStop (this.btPlay.currentLabels[1].frame);
			this.tempo.start();
			this.terminouVideo = false;
			this.addChildAt (this._screen, 0);
			
			this._idVideoAtual++;
						
			if (!repetirCarregado) {
				this.stream.close ();
				this.stream.play(urlVideo);
				//this.controlarPlayPause ();
			} else {
				this.stream.seek (0);
			}
			
			this.carregouMetaData = false;
			
			
			var evento:PlayerVideoEvent = new PlayerVideoEvent (PlayerVideoEvent.VIDEO_START, this.controleFullScreen, this.dadosVideo);			
			this.dispatchEvent (evento);
		}	
		
		private function estadoControles (estado:Boolean):void {			
			this.fundoControle.visible = estado;
			this.btPlay.visible = estado;
			this.btMute.visible = estado;
			this.btAmpliar.visible = estado;
			//this.vol.visible = estado;
			this.progressoTempo.visible = estado;
			this.progresso.visible = estado;
		}
		
		public function controlarPlayPause ():void {
			//trace (1);
			if (!this.terminouVideo) {
			//	trace (2);
				if (this.controlePlay) {
				//	trace (3);
					this.stream.pause();
					this.btPlay.gotoAndStop (this.btPlay.currentLabels[0].frame);
				} else {
				//	trace (4);
					this.stream.resume();
					this.btPlay.gotoAndStop (this.btPlay.currentLabels[1].frame);
				}
			} else {
			//	trace (6);
				this.iniciarVideo ();
			}
			this.controlePlay = !this.controlePlay;
			
			var eventoDisp:PlayerVideoEvent = new PlayerVideoEvent (PlayerVideoEvent.VIDEO_PLAY_PAUSE, this.controleFullScreen, this.dadosVideo, this.controlePlay);			
			this.dispatchEvent (eventoDisp);
		}
		
		private function alternarFullScreen ():void {
			this.controleFullScreen = !controleFullScreen;
			if (this.stage.displayState != StageDisplayState.FULL_SCREEN) {
				this.stage.displayState = StageDisplayState.FULL_SCREEN; 
			} else {
				this.stage.displayState = StageDisplayState.NORMAL;  
			}
		}		
		
		private function fimVideo ():void {
			this.terminouVideo = true;
			this.btPlay.gotoAndStop (this.btPlay.currentLabels[0].frame);
			this.controlePlay = !this.controlePlay;
			
			var dadosVideoFim:DadosVideo = this.dadosVideo;
			var eventoDisp:PlayerVideoEvent = new PlayerVideoEvent (PlayerVideoEvent.VIDEO_END, this.controleFullScreen, dadosVideoFim);			
			this.dispatchEvent (eventoDisp);
							
			if (this._idVideoAtual == this._listaDadosVideo.length) {
				var eventoDispFim:PlayerVideoEvent = new PlayerVideoEvent (PlayerVideoEvent.VIDEO_END_ALL, this.controleFullScreen, dadosVideoFim);			
				this.dispatchEvent (eventoDispFim);
				this._idVideoAtual = 0;
			} else {
				this.iniciarVideo ();
			}
		}
		
		// events
		/*
		private function onFullScreen (evento:FullScreenEvent):void {
			var eventoDisp:PlayerVideoEvent = new PlayerVideoEvent (PlayerVideoEvent.VIDEO_SCREEN, this.controleFullScreen);			
			this.dispatchEvent (eventoDisp);
			this._campo.appendText("\nonFullScreen: " + this.controleFullScreen);
		}
		
		private function onResizeScreen (evento:Event):void {
			this._campo.appendText("\nonResizeScreen: " + this.controleFullScreen);
		}	
		*/
		/*
		private function onLoadInfo (evento:Event):void {
			var inform:LoaderInfo = evento.target as LoaderInfo;
			try {
                this.dados.load(new URLRequest (inform.parameters.dadosXML));
            } catch (error:Error) {
                trace("Unable to load requested document.");
            }
		}
		*/
		
		/*
		public function onLoadDados(evento:Event):void	{					
			var dadosLoader:URLLoader = URLLoader(evento.target);
            var dadosXML:XML = new XML (dadosLoader.data);
			dadosXML.ignoreWhitespace = true;
			
			this.urlVideoAtual = String (dadosXML.video.@url);
			
			for each (var prop:XML in dadosXML.relacionados.video) {
				this.videosRelacionados.push (new DadosVideo (prop.@titulo, prop.@url, prop.@thumb));
			}
			this.iniciarVideo (this.urlVideoAtual);
		}
		*/
		/*
		public function onLoadDados(evento:Event):void	{	
			var carrega:CarregaDadosVideo = evento.target as CarregaDadosVideo; 
			var dadoVideoAtual:DadosVideo = this.carregaDadosVideo.dadosVideos[0];
			
			//this.urlVideoAtual = String (dadoVideoAtual.url);
			this.iniciarVideo (this.carregaDadosVideo.dadosVideos[this._idVideoAtual]);
		}
		*/
		public function onMetaData (infoObject:Object):void	{	
			this.carregouMetaData = true;
			this._duracao = infoObject.duration;	
			/*
			for (var c:String in infoObject) {
				trace (c + ": " + infoObject[c]);
			}	
			*/
		}		
		
		private function onProgClickArea (evento:BarraEvent):void {
			var seekTime:Number = Math.floor (evento.perc * this._duracao / 100);
			this.stream.seek(seekTime);
			if (this.terminouVideo) {				
				this.btPlay.gotoAndStop (this.btPlay.currentLabels[1].frame);
				this.tempo.start();				
				this.terminouVideo = false;
			}
			var eventoSeek:PlayerVideoEvent = new PlayerVideoEvent (PlayerVideoEvent.VIDEO_SEEK, this.fullScreen);
			eventoSeek.progresso = evento.perc;
			this.dispatchEvent (eventoSeek);
		}
		
		private function onProgDragStart (evento:BarraEvent):void {			
			if (!this.terminouVideo) {
				this.tempo.stop();
			}
			this.controlarPlayPause ();
		}
		
		private function onProgDragStop (evento:BarraEvent):void {
			this.stream.seek(evento.perc * this._duracao / 100);
			this.tempo.start();
			this.controlarPlayPause ();
			var eventoSeek:PlayerVideoEvent = new PlayerVideoEvent (PlayerVideoEvent.VIDEO_SEEK, this.fullScreen);
			eventoSeek.progresso = evento.perc;
			this.dispatchEvent (eventoSeek);
		}
		
		private function onProgDragMove (evento:BarraEvent):void {
			this.stream.seek(evento.perc * this._duracao / 100);
		}
		
		private function onVolDragMove (evento:BarraEvent):void {
			this.volumeAtual = evento.perc / 100;
			this.stream.soundTransform = new SoundTransform (this.volumeAtual);
			this.controleMute = true;
			this.btMute.gotoAndStop ("normal");
		}
		
		private function onTweenUpdateVol (evento:TweenEvent):void {
			this.vol.y = evento.value;
		}
		
		private function onTweenEndVol (evento:TweenEvent):void {
			this.onTweenUpdateVol (new TweenEvent (TweenEvent.TWEEN_UPDATE, evento.value) );
			Tween.removeTweenAt (this.volTween.id);
			this.volTween = null;
		}
		
		private function onMuteOver (evento:MouseEvent):void {  
			if (this.volTween != null) {
				Tween.removeTweenAt (this.volTween.id);
				this.volTween = null;
			}
			
			this.volTween = new Tween (this.vol.y, this.volYInicial, 500);
			this.volTween.addEventListener (TweenEvent.TWEEN_UPDATE, this.onTweenUpdateVol);
			this.volTween.addEventListener (TweenEvent.TWEEN_END, this.onTweenEndVol);
		}
		
		private function onMuteOut (evento:MouseEvent):void {   
			if (this.volTween != null) {
				Tween.removeTweenAt (this.volTween.id);
				this.volTween = null;
			}
			
			this.volTween = new Tween (this.vol.y, this.volYInicial + this.vol.height, 500);
			this.volTween.addEventListener (TweenEvent.TWEEN_UPDATE, this.onTweenUpdateVol);
			this.volTween.addEventListener (TweenEvent.TWEEN_END, this.onTweenEndVol);
		}
		
		private function onMuteClick (evento:MouseEvent):void {        	
			if (this.controleMute) {
				this.stream.soundTransform = new SoundTransform (0);
				this.btMute.gotoAndStop ("mute");
				this.vol.perc = 0;
			} else {
				this.stream.soundTransform = new SoundTransform (this.volumeAtual);
				this.vol.perc = this.volumeAtual * 100;
				this.btMute.gotoAndStop ("normal");
			}
			this.controleMute = !this.controleMute;
		}
		
		private function onScreenDoubleClick (evento:MouseEvent):void {
			this.alternarFullScreen ();
			this.controlarPlayPause ();
		}
		
		private function onScreenClick (evento:MouseEvent):void {
			this.controlarPlayPause ();
		}
		
		private function onAmpliarClick (evento:MouseEvent):void {
			this.alternarFullScreen ();
		}
		
		private function onPlayClick (evento:MouseEvent):void {
			this.controlarPlayPause ();
		}
		
		private function onTimer (evento:TimerEvent):void {			
			var atual:Number = this.stream.time;
			var total:Number = this._duracao;
			var tempoTotal:Date = new Date (null,null,null,null,null,total);
			var minTotal:String = (tempoTotal.getMinutes() < 10) ? "0" + tempoTotal.getMinutes() : String (tempoTotal.getMinutes());
			var segTotal:String = (tempoTotal.getSeconds() < 10) ? "0" + tempoTotal.getSeconds() : String (tempoTotal.getSeconds());
			
			var tempoAtual:Date = new Date (null,null,null,null,null,atual);
			var minAtual:String = (tempoAtual.getMinutes() < 10) ? "0" + tempoAtual.getMinutes() : String (tempoAtual.getMinutes());
			var segAtual:String = (tempoAtual.getSeconds() < 10) ? "0" + tempoAtual.getSeconds() : String (tempoAtual.getSeconds());
			
			if (!this.terminouVideo) {
				if (this.carregouMetaData) {
					this.progressoTempo.statusTime.text = minAtual + ":" + segAtual + " / " + ((minTotal == "NaN") ? "00" : minTotal) + ":" +  ((segTotal == "NaN") ? "00" : segTotal);
				} else {
					this.progressoTempo.statusTime.text = "--:-- / --:--";
				}
				
				this.progresso.buffer.width = this.stream.bytesLoaded / this.stream.bytesTotal * this.progresso.area.width;
				this.progresso.prog.width = atual / total * this.progresso.area.width;
				this.progresso.drag.x = this.progresso.prog.x + this.progresso.prog.width;
			}
			
			if (this.stream.bufferLength * (this.duracao / 1000) / 100 >= 15) {
				this.controlarPlayPause ();
			}
			
			var atualRound:Number = Math.floor (atual * 10) / 10;
			var totalRound:Number = Math.floor (total * 10) / 10;
			
			//this._campo.text = String (atualRound) + " == " + String (totalRound);
			if (atualRound == totalRound) {
				this.tempo.stop ();				
				this.fimVideo ();
			}
		}
				
		private function asyncErrorHandler (event:AsyncErrorEvent):void {
			// ignore error
		}
	}	
}